<template>
    <div class="base64-container">
        <div class="control-panel">
            <n-radio-group v-model:value="mode" class="mode-select">
                <n-radio-button key="encode" value="encode">编码</n-radio-button>
                <n-radio-button key="decode" value="decode">解码</n-radio-button>
            </n-radio-group>

            <n-radio-group v-if="mode === 'encode'" v-model:value="sourceType" class="source-select">
                <n-radio-button key="text" value="text">文本</n-radio-button>
                <n-radio-button key="file" value="file">文件</n-radio-button>
            </n-radio-group>
        </div>

        <div class="content-panel">
            <!-- 输入区域 -->
            <div class="input-section">
                <div class="section-header">
                    <span>输入</span>
                    <div class="actions">
                        <n-button quaternary size="small" @click="clearInput">
                            清空
                        </n-button>
                    </div>
                </div>
                
                <template v-if="mode === 'decode' || sourceType === 'text'">
                    <n-input
                        v-model:value="inputText"
                        type="textarea"
                        :autosize="{ minRows: 5, maxRows: 10 }"
                        :placeholder="mode === 'decode' ? '请输入要解码的Base64文本' : '请输入要编码的文本'"
                    />
                </template>
                <template v-else>
                    <div class="file-input">
                        <n-upload
                            :show-file-list="false"
                            @change="handleFileChange"
                            accept="*/*"
                        >
                            <n-button>选择文件</n-button>
                        </n-upload>
                        <span v-if="selectedFile" class="file-name">
                            {{ selectedFile.name }}
                        </span>
                    </div>
                </template>
            </div>

            <!-- 输出区域 -->
            <div class="output-section">
                <div class="section-header">
                    <span>输出</span>
                    <div class="actions">
                        <n-button quaternary size="small" @click="copyOutput" :disabled="!outputText">
                            复制
                        </n-button>
                        <n-button quaternary size="small" @click="clearOutput" :disabled="!outputText">
                            清空
                        </n-button>
                        <n-button
                            v-if="mode === 'decode' && isBase64Image"
                            quaternary
                            size="small"
                            @click="downloadImage"
                            :disabled="!outputText"
                        >
                            下载图片
                        </n-button>
                    </div>
                </div>
                <template v-if="isBase64Image">
                    <div class="image-preview">
                        <img :src="outputText" alt="Base64 Image" />
                    </div>
                </template>
                <template v-else>
                    <n-input
                        v-model:value="outputText"
                        type="textarea"
                        :autosize="{ minRows: 5, maxRows: 10 }"
                        readonly
                        placeholder="输出结果将显示在这里"
                    />
                </template>
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import view from '@renderer/util/ui/ViewUtil'

// 模式：编码/解码
const mode = ref<'encode' | 'decode'>('encode')
// 来源类型：文本/文件
const sourceType = ref<'text' | 'file'>('text')
// 输入文本
const inputText = ref('')
// 输出文本
const outputText = ref('')
// 选中的文件
const selectedFile = ref<File | null>(null)

// 是否可以处理
const canProcess = computed(() => {
    // 解码模式或文本输入模式下，检查输入文本
    if (mode.value === 'decode' || sourceType.value === 'text') {
        return inputText.value.trim() !== ''
    }
    // 文件模式下，检查是否选择了文件
    return selectedFile.value !== null
})

// 是否是Base64图片
const isBase64Image = computed(() => {
    if (mode.value === 'decode' && outputText.value) {
        return outputText.value.startsWith('data:image/')
    }
    return false
})

// 文件上传前的验证
const handleBeforeUpload = (data: { file: File }) => {
    if (mode.value === 'decode') {
        // 解码模式下只允许上传文本文件
        const isTextFile = data.file.type === 'text/plain' || 
                          data.file.name.endsWith('.txt') || 
                          data.file.name.endsWith('.text')
        
        if (!isTextFile) {
            view.alertErrorMessage('解码模式下只能选择文本文件')
            return false
        }
    }
    return true
}

// 使用防抖函数来避免频繁处理
const debounce = (fn: Function, delay: number) => {
    let timer: number | null = null
    return (...args: any[]) => {
        if (timer) clearTimeout(timer)
        timer = setTimeout(() => {
            fn.apply(null, args)
        }, delay) as unknown as number
    }
}

// 自动处理函数
const autoProcess = debounce(async () => {
    if (!canProcess.value) return
    await handleProcess()
}, 500)

// 监听输入变化
watch(inputText, () => {
    if (sourceType.value === 'text') {
        autoProcess()
    }
})

// 监听模式变化，重新处理
watch([mode, sourceType], () => {
    if (canProcess.value) {
        autoProcess()
    }
})

// 修改文件处理函数，使其自动处理
const handleFileChange = async (data: { file: File, fileList: File[] }) => {
    // 确保有文件被选择
    if (!data.file || !data.file.file) return
    
    const file = data.file.file as File
    
    // 再次验证文件类型（双重保险）
    if (mode.value === 'decode') {
        const isTextFile = file.type === 'text/plain' || 
                          file.name.endsWith('.txt') || 
                          file.name.endsWith('.text')
        
        if (!isTextFile) {
            view.alertErrorMessage('解码模式下只能选择文本文件')
            return
        }
    }
    
    selectedFile.value = file
    const reader = new FileReader()
    
    reader.onload = () => {
        if (mode.value === 'encode') {
            inputText.value = reader.result as string
        } else {
            inputText.value = reader.result as string
        }
        // 文件加载完成后自动处理
        autoProcess()
    }

    reader.onerror = () => {
        view.alertErrorMessage('文件读取失败')
        selectedFile.value = null
    }

    if (mode.value === 'encode') {
        reader.readAsDataURL(file)
    } else {
        reader.readAsText(file)
    }
}

// 编码 UTF-8 字符串
const encodeUTF8 = (str: string): string => {
    return window.btoa(unescape(encodeURIComponent(str)))
}

// 解码 UTF-8 字符串
const decodeUTF8 = (str: string): string => {
    try {
        return decodeURIComponent(escape(window.atob(str)))
    } catch {
        throw new Error('解码失败')
    }
}

// 处理编解码
const handleProcess = async () => {
    try {
        if (mode.value === 'encode') {
            // 编码
            if (sourceType.value === 'text') {
                outputText.value = encodeUTF8(inputText.value)
            } else if (inputText.value) {
                // 如果是文件，保留完整的 Data URL
                outputText.value = inputText.value
            }
        } else {
            // 解码
            try {
                if (inputText.value.startsWith('data:')) {
                    // 如果是 Data URL，直接作为图片处理
                    outputText.value = inputText.value
                } else {
                    const decoded = decodeUTF8(inputText.value)
                    outputText.value = decoded
                    
                    // 如果解码后是 Data URL，可能是图片
                    if (decoded.startsWith('data:image/')) {
                        outputText.value = decoded
                    }
                }
            } catch {
                view.alertErrorMessage('解码失败，请确保输入正确的 Base64 字符串')
            }
        }
    } catch (error) {
        view.alertErrorMessage('处理失败')
        console.error('Base64 处理失败:', error)
    }
}

// 复制输出
const copyOutput = async () => {
    try {
        await navigator.clipboard.writeText(outputText.value)
        view.alertSuccessMessage('复制成功')
    } catch {
        view.alertErrorMessage('复制失败')
    }
}

// 清空输入
const clearInput = () => {
    inputText.value = ''
    selectedFile.value = null
}

// 清空输出
const clearOutput = () => {
    outputText.value = ''
}

// 下载图片
const downloadImage = () => {
    if (!outputText.value) return

    const link = document.createElement('a')
    link.download = `decoded-image-${Date.now()}.png`
    link.href = outputText.value
    link.click()
}

// 监听模式变化
watch(mode, (newMode) => {
    // 解码模式下强制使用文本输入
    if (newMode === 'decode') {
        sourceType.value = 'text'
    }
    // 清空输入和输出
    clearInput()
    clearOutput()
})
</script>

<style scoped>
.base64-container {
    height: 100%;
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.control-panel {
    display: flex;
    gap: 16px;
    align-items: center;
}

.content-panel {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 16px;
    min-height: 0;
}

.input-section,
.output-section {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-height: 0;
}

.section-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.actions {
    display: flex;
    gap: 8px;
}

.file-input {
    display: flex;
    gap: 8px;
    align-items: center;
    padding: 16px;
    border: 1px dashed var(--border-color);
    border-radius: 4px;
}

.file-name {
    color: var(--text-color-2);
    font-size: 14px;
}

.image-preview {
    flex: 1;
    min-height: 0;
    padding: 16px;
    border: 1px solid var(--border-color);
    border-radius: 4px;
    overflow: auto;
    display: flex;
    align-items: center;
    justify-content: center;
}

.image-preview img {
    max-width: 100%;
    max-height: 100%;
}
</style>